#include "reg51.h"
#include "intrins.h"
#include <stdio.h>
#include <math.h>

#define FOSC        11059200UL
#define BRT         (65536 - FOSC / 9600 / 4)

#define SYSCLK       1000000UL

#define OLED_WR_ADD 0x78
#define OLED_RD_ADD 0x79

#define I2CCFG      (*(unsigned char volatile xdata *)0xfe80)
#define I2CMSCR     (*(unsigned char volatile xdata *)0xfe81)
#define I2CMSST     (*(unsigned char volatile xdata *)0xfe82)
#define I2CSLCR     (*(unsigned char volatile xdata *)0xfe83)
#define I2CSLST     (*(unsigned char volatile xdata *)0xfe84)
#define I2CSLADR    (*(unsigned char volatile xdata *)0xfe85)
#define I2CTXD      (*(unsigned char volatile xdata *)0xfe86)
#define I2CRXD      (*(unsigned char volatile xdata *)0xfe87)




sbit    SDA     =   P3^3;
sbit    SCL     =   P3^2;
sfr 		P5   = 0xC8;
sbit 		P54 = P5^4;

sfr     AUXR    =   0x8e;
sfr     P3M1    =   0xb1;
sfr     P3M0    =   0xb2;
sfr     P5M1    =   0xc9;
sfr     P5M0    =   0xca;
sfr 		T2H  		= 	0xd6;               //???2?8?
sfr 		T2L   	= 	0xd7;               //???2?8?
sfr     P_SW2   =   0xba;

bit busy,end_flag=0,end_flag2=0;
char rptr,wptr,wptr2;
char buffer[90],buffer2[90];
unsigned char stat=0,stat2=0;

void init_oled(void);
void OLED_Clear(void);
void printn(unsigned char num, unsigned char page, unsigned char col);
void printm(unsigned char num, unsigned char page, unsigned char col);
void printt(unsigned char page); 
void printb(unsigned char page); 

//8x16 ColxRow
unsigned  char  code  Num[] = {																										
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//"0"
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//"1"
0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//"2"
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//"3"
0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//"4"
0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//"5"
0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//"6"
0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//"7"
0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//"8"
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//"9"
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//"."
0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//"M"
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00//"NULL"
};

unsigned char code big_s_arr[]={
	0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00//S
};

unsigned char code big_c_arr[]={
	0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00//C
};

unsigned char code Title[]={
0x00,0x00,0x00,0x18,0x28,0xD0,0x20,0x20,0x40,0xA8,0x14,0x2A,0x15,0x0A,0x04,0x00,//icon
0x10,0x28,0x54,0x2A,0x14,0x0A,0x01,0x02,0x01,0xAA,0x00,0x2A,0x00,0x0A,0x00,0x02,//icon

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//NULL
0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L	
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 
0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//null
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//.
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//null
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};	

unsigned char code bottom[]={
0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,// S 
0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,// p 
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,// e
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,// e 
0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,// d
0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,// : 
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//null
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//null
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,// .
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//null
0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,// k
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,// m
0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,// "/"
0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,// h 
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//null
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 //null

};


unsigned  char  code Num32[] = {
0x00,0x00,0x00,0x80,0x80,0xC0,0xC0,0x40,0xC0,0xC0,0x80,0x80,0x00,0x00,0x00,0x00,//"0"-page 0
0x00,0xFC,0xFF,0xFF,0x0F,0x01,0x00,0x00,0x00,0x01,0x0F,0xFF,0xFF,0xFC,0x00,0x00,//"0"-page 1
0x00,0x1F,0x7F,0xFF,0xF8,0xC0,0x80,0x00,0x80,0xC0,0xFC,0xFF,0x3F,0x0F,0x00,0x00,//"0"-page 2
0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,//"0"-page 3

0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//"1"-page 0
0x00,0x00,0x00,0x01,0x01,0x01,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//"1"-page 1
0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,//"1"-page 2
0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,//"1"-page 3

0x00,0x00,0x00,0x80,0xC0,0xC0,0x40,0x40,0x40,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,//"2"-page 0
0x00,0x0E,0x1F,0x1F,0x1F,0x00,0x00,0x00,0x80,0xE0,0xFF,0x7F,0x3F,0x0E,0x00,0x00,//"2"-page 1
0x00,0xC0,0xE0,0xF0,0xB8,0x9C,0x8E,0x87,0x83,0x81,0xC0,0xE0,0xF0,0x70,0x00,0x00,//"2"-page 2
0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,//"2"-page 3

0x00,0x00,0x80,0x80,0xC0,0x40,0x40,0x40,0xC0,0xC0,0x80,0x80,0x00,0x00,0x00,0x00,//"3"-page 0
0x00,0x02,0x07,0x07,0x07,0x40,0x40,0x40,0xE0,0xFF,0xBF,0x9F,0x0F,0x00,0x00,0x00,
0x00,0x70,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x80,0x81,0xFF,0xFF,0x7F,0x1C,0x00,0x00,
0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xE0,0xE0,0x00,0x00,0x00,0x00,0x00,//"4"-page 0
0x00,0x00,0x80,0xE0,0x78,0x3C,0x0F,0x07,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,
0x04,0x07,0x07,0x05,0x04,0x04,0x04,0x84,0xFF,0xFF,0xFF,0x84,0x04,0x04,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,

0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,//"5"-page 0
0x00,0x00,0xFF,0xFF,0xCF,0x60,0x20,0x20,0x20,0x60,0xE0,0xC0,0x80,0x00,0x00,0x00,
0x00,0x38,0xF8,0xF9,0xF8,0x00,0x00,0x00,0x80,0xC0,0xFF,0xFF,0x7F,0x1F,0x00,0x00,
0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0x40,0x40,0xC0,0xC0,0xC0,0x80,0x00,0x00,0x00,//"6"-page 0
0x00,0xF8,0xFE,0xFF,0xCF,0x61,0x60,0x20,0x20,0x63,0xE3,0xC3,0xC3,0x00,0x00,0x00,
0x00,0x1F,0x7F,0xFF,0xF1,0xC0,0x80,0x00,0x00,0x80,0xF3,0xFF,0x7F,0x3F,0x00,0x00,
0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x40,0x00,0x00,//"7"-page 0
0x00,0x07,0x07,0x03,0x01,0x00,0x80,0xE0,0xF0,0x7C,0x0F,0x03,0x01,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xC0,0xFC,0xFF,0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x80,0x80,0xC0,0xC0,0x40,0x40,0x40,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,//"8"-page 0
0x00,0x0E,0x3F,0xBF,0xF1,0xE0,0xE0,0xC0,0xC0,0xE0,0xF3,0x3F,0x1F,0x0E,0x00,0x00,
0x00,0x7E,0xFF,0xFF,0x81,0x80,0x00,0x00,0x01,0x83,0xC7,0xFF,0x7E,0x3C,0x00,0x00,
0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x80,0x80,0xC0,0xC0,0x40,0x40,0x40,0xC0,0x80,0x80,0x00,0x00,0x00,0x00,//"9"-page 0
0x00,0xFE,0xFF,0xFF,0x83,0x00,0x00,0x00,0x00,0x80,0xEF,0xFF,0xFF,0xFC,0x00,0x00,
0x00,0x00,0xE1,0xE3,0xE3,0x83,0x02,0x82,0x83,0xE3,0xFF,0x7F,0x1F,0x07,0x00,0x00,
0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//"."-page 0
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x80,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//":"-page 0
0x00,0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,


0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//"NULL"-page 0
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};


void UartInit(void)		//9600bps@11.059200MHz
{
	
    SCON = 0x50;
    TMOD = 0x00;
    TL1 = BRT;
    TH1 = BRT >> 8;
    TR1 = 1;
    AUXR = 0x40;
    wptr = 0x00;
    rptr = 0x00;
    busy = 0;
}

void UartIsr() interrupt 4
{
	unsigned char temp;
    if (RI)
    {
        RI = 0;
				temp =SBUF;
			switch(stat){
				case 0:  stat=(temp=='$')? 1:0; break;
			  case 1:  stat=(temp=='G')? 2:0; break;
				case 2:  stat=(temp=='P')? 3:0; break; 
				case 3:  stat=(temp=='R')? 4:0; break;
				case 4:  stat=(temp=='M')? 5:0; break;
				case 5:  stat=(temp=='C')? 6:0; break; 
				case 6:  if (temp==0x0a) 
								   end_flag=1; 
								else
							    {
									  buffer[wptr++]=temp; 
									  if (wptr==89)  wptr =88;
							    }
								break;
				default:
					  {
							stat=0;
							wptr=0;
										}
					}					
			
					switch(stat2){
				case 0:  stat2=(temp=='$')? 1:0; break;
			  case 1:  stat2=(temp=='G')? 2:0; break;
				case 2:  stat2=(temp=='P')? 3:0; break; 
				case 3:  stat2=(temp=='G')? 4:0; break;
				case 4:  stat2=(temp=='G')? 5:0; break;
				case 5:  stat2=(temp=='A')? 6:0; break; 
				case 6:  if (temp==0x0a) 
								   end_flag2=1; 
								else
							    {
									  buffer2[wptr2++]=temp; 
									  if (wptr2==89)  wptr2 =88;
							    }
								break;
				default:
					  {
							stat2=0;
							wptr2=0;
										}
					}					
			}	

		if (TI)
    {
        TI = 0;
        busy = 0;
    }
}

void UartSend(char dat)
{
    while (busy);
    busy = 1;
    SBUF = dat;
}

void UartSendStr(char *p)
{
    while (*p)
    {
        UartSend(*p++);
    }
}

void Delayms(int tick)		//
{
	unsigned char i, j;

	i = 195;
	j = 138;
	while(tick--)
		do
	{
		while (--j);
	} while (--i);

}

void Wait()
{
    while (!(I2CMSST & 0x40));
    I2CMSST &= ~0x40;
}

void Start()
{
    I2CMSCR = 0x01;                             //??START??
    Wait();
}

void Stop()
{
    I2CMSCR = 0x06;                             //??STOP??
    Wait();
}

void SendData(char dat)
{
    I2CTXD = dat;                               //?????????
    I2CMSCR = 0x02;                             //??SEND??
    Wait();
}

void RecvACK()
{
    I2CMSCR = 0x03;                             //???ACK??
    Wait();
}

char RecvData()
{
    I2CMSCR = 0x04;                             //??RECV??
    Wait();
    return I2CRXD;
}

void SendACK()
{
    I2CMSST = 0x00;                             //??ACK??
    I2CMSCR = 0x05;                             //??ACK??
    Wait();
}

void SendNAK()
{
    I2CMSST = 0x01;                             //??NAK??
    I2CMSCR = 0x05;                             //??ACK??
    Wait();
}

//????OLED-------------------------------------
void transfer_command(int data1)
{
		Start();
		SendData(OLED_WR_ADD); //0x78
		RecvACK();
		SendData(0x00); //
		RecvACK();	
		SendData(data1); 
		RecvACK();	
		Stop();
}

//????OLED----------------------------------------
void transfer_data(int data1)
{
		Start();
		SendData(OLED_WR_ADD); //0x78
		RecvACK();	
		SendData(0x40); //
		RecvACK();	
		SendData(data1); 
		RecvACK();	
		Stop();
}

/*------------------------------------------
ssd1306 RAM is 128(Horizontal)x64(Vertical).
screen is divide by 8 page in vertical dirction.
Each page is one byte high.
   _Col 0____________________Col 127__
	|  -->         Page0   -->        <-|
	|  -->         Page1   -->        <-|
	|  -->         Page2   -->        <-|
	|  -->         Page3   -->        <-|
  |  -->         Page4   -->        <-|
	|  -->         Page5   -->        <-|
	|  -->         Page6   -->        <-|
  |__-->_________Page7___-->________<-|
Page addressing  is default mode after power on or reset.
In page addressing mode, the col address pointer is added by 1 and reset to zero 
when overflow automatictly.There are 3 steps to access RAM data:
1. Set start page address by command 0xB0~0xB7(mapping to Page0~Page7)
2. Set lower address  pointer by command 0x00h~0x0Fh
3. Set upper address  pointer by command 0x10h~0x1Fh

Horizontal address mode:
   _Col 0____________________Col 127__
	|  -->         Page0   -->          | to Page1
	|  -->         Page1   -->          | to Page2
	|  -->         Page2   -->          | to Page3
	|  -->         Page3   -->          | to Page4
  |  -->         Page4   -->          | to Page5
	|  -->         Page5   -->          | to Page6
	|  -->         Page6   -->          | to Page7
  |__-->_________Page7___-->_________ | to Page0


Vertical address mode:
   _Col 0__Col 1_____________Col 127__
	|   |     | |  Page0                | 
	|   |     | |  Page1                | 
	|   |     | |  Page2                | 
	|   |    /  |  Page3                | 
  |   |   /   |  Page4                | 
	|   |  /    |  Page5                | 
	|   | /     | /Page6                | 
  |____/______|/_Page7________________| 
	 to Col 1   to Col n+1       to Col 0

--------------------------------------------*/

void printt(unsigned char page)
{
	      unsigned char i,x,index;
        
	      for(i=0;i<15;i++)
				{
					index=i*16; 										//calculate the start address of character in matrix[].
					transfer_command(0xb0+page);				//select the page x. row range is [0:7]
					transfer_command((i*8)&0x0f);				//set low column address [0x00: 0x0f]
					transfer_command((i*8)>>4|0x10);	//set high column address which rage is [0x10: 0x1f]
					for(x=index;x<index+8;x++)    	//write the upper 8 Bytes in Page upper 
					{
						transfer_data(Title[x]);   
						
					} 
				
					transfer_command(0xb1+page);				//turn to next Page which is on the below
					transfer_command((i*8)&0x0f);     	//set low column address [0x00: 0x0f]
					transfer_command((i*8)>>4|0x10);	//set high column address which rage is [0x10: 0x1f]
					for(x=index+8;x<index+16;x++) //write the lower 8 Bytes in Page lower         
					{
					  if (x==254) break;
						transfer_data(Title[x]);
					} 
				}
}

void printb(unsigned char page)
{
		   unsigned char i,x;
		   unsigned int index;
        
	      for(i=0;i<15;i++)
				{
					index=i*16; 										    //calculate the start address of character in matrix[].
					
					transfer_command(0xb0+page);				//select the page x. row range is [0:7]
					transfer_command((i*8)&0x0f);				//set low column address [0x00: 0x0f]
					transfer_command((i*8)>>4|0x10);	  //set high column address which rage is [0x10: 0x1f]
					for(x=index;x<(index+8);x++)    	    //write the upper 8 Bytes in Page upper 
					{
						transfer_data(bottom[x]);   
						
					} 
					
				
					transfer_command(0xb1+page);				//turn to next Page which is on the below
					transfer_command((i*8)&0x0f);     	//set low column address [0x00: 0x0f]
					transfer_command((i*8)>>4|0x10);	  //set high column address which rage is [0x10: 0x1f]
					for(x=index+8;x<(index+16);x++)       //write the lower 8 Bytes in Page lower         
					{
						if (x==254) break;
						transfer_data(bottom[x]);
					} 
					
				}
}


/*-------------output 8(col)x16(row) data to ssd1306 RAM-------------*/

void printn(unsigned char page, unsigned char num,  unsigned char *arr) 
{
        unsigned char i,col;
        col=num*8; 										//calculate the start address of character in matrix[].
				transfer_command(0xb0+page);				//select the page x. row range is [0:7]
				transfer_command(col&0x0f);				//set low column address [0x00: 0x0f]
				transfer_command((col>>4)|0x10);	//set high column address which rage is [0x10: 0x1f]
				for(i=0;i<8;i++)    	//write the upper 8 Bytes in Page upper 
        {
					transfer_data(arr[i]);   
        } 
				
        transfer_command(0xb1+page);				//turn to next Page which is on the below
				transfer_command(col&0x0f);     	//set low column address [0x00: 0x0f]
				transfer_command((col>>4)|0x10);	//set high column address which rage is [0x10: 0x1f]
        for(i=8;i<16;i++) //write the lower 8 Bytes in Page lower         
        {
					transfer_data(arr[i]);
        } 
}

/*-------------output 16(col)x32(row) data to ssd1306 RAM-------------*/

void printm(unsigned char num, unsigned char page, unsigned char col) 
{
        unsigned char i,j,p;
	      unsigned int index;
				p=page%7;
        index=num*64; 										//calculate the start address of character in matrix[].
				for(i=0;i<4;i++)
				{
					transfer_command(0xb0+p);				//select the page x. row range is [0:7]
					transfer_command(col&0x0f);				//set low column address [0x00: 0x0f]
					transfer_command((col>>4)|0x10);	//set high column address which rage is [0x10: 0x1f]
					for(j=0;j<16;j++)    	//write the 8 Bytes in Page upper 
					{ 
						transfer_data(Num32[index+i*16+j]);   
					} 
					p++;
			  }       
}

void OLED_Clear(void)
{
	unsigned char  i,j;
	
	Start();		// ????
	SendData(OLED_WR_ADD);
	RecvACK();	
	SendData(0x00);	// ??? Co='0' C/D='000 0000'
	RecvACK();	
	SendData(0X20);	// ??GDDRAM??
	RecvACK();	
	SendData(0X00);	// ?????? 
	RecvACK();	
	SendData(0X21);	// ??????????
	RecvACK();	
	SendData(0X00);	// ????? 0
	RecvACK();	
	SendData(0X7F);	// ????? 127
	RecvACK();	
	SendData(0X22);	// ??????????
	RecvACK();	
	SendData(0X00);	// ????? 0
	RecvACK();	
	SendData(0X07);	// ????? 7
	RecvACK();	
	// ????'0'
	Start();		// ?????
	SendData(OLED_WR_ADD);
	RecvACK();	
	SendData(0X40);	// ???  Co='0' C/D='100 0000'
	RecvACK();	
	for(i=0; i<8; i++){
		for(j=0; j<128; j++){
			SendData(0X00);
			RecvACK();	
		}
	}
	
   Stop();
}


//???OLED------------------------------------------
void init_oled()
{
	//__delay_ms(1000);
	transfer_command(0xae);//???
	transfer_command(0xd5);//????
	transfer_command(0x80);
	transfer_command(0xa8);//duty??
	transfer_command(0x3f);// duty=1/64
	transfer_command(0xd3);// ????
	transfer_command(0x00);
	transfer_command(0x40);//???
	transfer_command(0x8d);//????
	transfer_command(0x14);
	transfer_command(0x20);//page address mode
	transfer_command(0x02);
	transfer_command(0xc8);//?????:????
	transfer_command(0xa1);//?????:????
	transfer_command(0xda);//sequential configuration
	transfer_command(0x12);
	transfer_command(0x81);//?????
	transfer_command(0xcf);//???????
	transfer_command(0xd9);//set pre-charge period
	transfer_command(0xf1);
	transfer_command(0xdb);//set VCOMH deselect level
	transfer_command(0x40);
	transfer_command(0xaf);//???
}


void main()
{  
	  unsigned char hour_h,hour_l,min_h,min_l,tick=0,i,alti_h,alti_m,alti_l,alti_ml;
	  unsigned char last_hh,last_hl,last_mh,last_ml,last_ah,last_am,last_al,last_aml,LOC=0;
	  unsigned char last_sph,last_spm,last_spl,last_spml;
	  unsigned int sp_h,sp_m,sp_l,sp_ml;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P3M0 &= ~0x01; P3M1 |= 0x01; 
	  P5M0 = 0x00;
    P5M1 = 0x00;
	  UartInit();
	  ES = 1;
    EA = 1;
	  P_SW2 = 0x80;
	  I2CCFG = 0xe0;                              //??I2C????
	  I2CMSST = 0x00;
	  init_oled();
		OLED_Clear();
		printt(0);//display top 
		printb(6);//display bottom 
			   	
	  while (1)
		{
         if(end_flag==1)
					 {
						  if(buffer[1]!=last_hh||buffer[2]!=last_hl||buffer[3]!=last_mh||buffer[4]!=last_ml)
  						{
							hour_h=(((buffer[1]-'0')*10+buffer[2]-'0'+8)%24)/10;
							hour_l=(((buffer[1]-'0')*10+buffer[2]-'0'+8)%24)%10;
							min_h=buffer[3]-'0';
							min_l=buffer[4]-'0';
	
							last_hh=buffer[1];
							last_hl=buffer[2];
							last_mh=buffer[3];
							last_ml=buffer[4];
								
							
							printm(hour_h,2,16);
							printm(hour_l,2,32);
							printm(min_h,2,64);
							printm(min_l,2,80);	
							
							if (buffer[12]=='A')
							 { printn(0,5,big_c_arr); LOC=1;}
						  else
							 { printn(0,5,big_s_arr); LOC=0;} 									
							}	

							if(buffer[39]!=last_sph||buffer[40]!=last_spm||buffer[41]!=last_spl||buffer[43]!=last_spml)
							{
								sp_h=(((buffer[39]-'0')*100+(buffer[40]-'0')*10+buffer[41]-'0'+(buffer[43]-'0')*0.1)*1.825/100)*16;
								sp_m=((int)(((buffer[39]-'0')*100+(buffer[40]-'0')*10+buffer[41]-'0'+(buffer[43]-'0')*0.1)*1.825)/10)*16;
								sp_l=(((int)(((buffer[39]-'0')*100+(buffer[40]-'0')*10+buffer[41]-'0'+(buffer[43]-'0')*0.1)*1.825))%10)*16;
								sp_ml=((int)(((buffer[39]-'0')*1000+(buffer[40]-'0')*100+(buffer[41]-'0')*10+buffer[43]-'0')*1.825)%10)*16;
								
								//printn(6,5, &Num[(unsigned char)sp_h]);
								printn(6,6, &Num[(unsigned char)sp_m]);
								printn(6,7, &Num[(unsigned char)sp_l]);
								printn(6,9, &Num[(unsigned char)sp_ml]);
								
								last_sph=buffer[39];
								last_spm=buffer[40];
								last_spl=buffer[41];
								last_spml=buffer[43];
							}
						  end_flag=0;
						  wptr=0; 
						  stat=0;				 
						}
							
					if(end_flag2==1)
							{
							// P54=!P54;		
						//	if(buffer[49]!=last_ah||buffer[50]!=last_am||buffer[51]!=last_al||buffer[53]!=last_aml)
							{
								if(LOC==1)
								{
								alti_h=(buffer2[49]-'0')*16;
								alti_m=(buffer2[50]-'0')*16;
								alti_l=(buffer2[51]-'0')*16;
								alti_ml=(buffer2[53]-'0')*16;
								
								printn(0,8, &Num[alti_h]);
								printn(0,9, &Num[alti_m]);
								printn(0,10, &Num[alti_l]);
								printn(0,12, &Num[alti_ml]);
								}
								last_ah=buffer[49];
								last_am=buffer[50];
								last_al=buffer[51];
								last_aml=buffer[53];
							
							}
							end_flag2=0;	
							wptr2=0; 
							stat2=0;
						}
						 //ES=1;
						 //for(i=0;i<wptr;i++)
						 //  UartSend(buffer[i]);
										 
					 
         if(tick<=3)
					printm(11,2,48);
				 else
					printm(12,2,48); 					 
				 Delayms(15);
				if (++tick==6) tick =0;
						
        } 
}

